package com.example.registar;

import com.example.anno.EnableMapper;
import com.example.proxy.MapperProxy;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;

import java.beans.Introspector;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.Map;

public class MapperRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> attrs =  importingClassMetadata.getAnnotationAttributes(EnableMapper.class.getName());
        String[] basePackages = (String[]) attrs.get("basePackages");
        // 关闭默认过滤器，添加业务过滤逻辑
        ClassPathBeanDefinitionScanner scanner =
                new ClassPathBeanDefinitionScanner(registry, false) {
                    @Override
                    public boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
                        return metadataReader.getClassMetadata().isInterface() &&
                                metadataReader.getClassMetadata().getClassName().endsWith("Mapper");
                    }
                    @Override
                    public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                        AnnotationMetadata metadata = beanDefinition.getMetadata();
                        return metadata.isInterface() && metadata.getClassName().endsWith("Mapper");
                    }
                };
        scanner.addIncludeFilter((mr, mf) -> true);   // 全部收下
        // scanner.scan(basePackages);

        /* 1. 只扫，不注册 */
        for (String pkg : basePackages) {
            for (BeanDefinition candidate : scanner.findCandidateComponents(pkg)) {
                String className = candidate.getBeanClassName();
                try {
                    Class<?> mapperInterface = Class.forName(className);

                    /* 2. 生成代理 FactoryBean 定义 */
                    AbstractBeanDefinition proxyBd =
                            BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                                    .addConstructorArgValue(mapperInterface)
                                    .getBeanDefinition();

                    /* 3. beanName 用 Spring 默认策略（首字母小写） */
                    String beanName = Introspector.decapitalize(mapperInterface.getSimpleName());

                    /* 4. 注册 */
                    registry.registerBeanDefinition(beanName, proxyBd);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static class MapperFactoryBean implements FactoryBean<Object> {

        private final Class<?> mapperInterface;

        public MapperFactoryBean(Class<?> mapperInterface) {
            this.mapperInterface = mapperInterface;
        }

        @Override
        public Object getObject() throws Exception {
            return Proxy.newProxyInstance(mapperInterface.getClassLoader(),
                    new Class<?>[]{mapperInterface},
                    new MapperProxy(mapperInterface));
        }

        @Override
        public Class<?> getObjectType() {
            return mapperInterface;
        }

        @Override
        public boolean isSingleton() {
            return true;
        }
    }
}
